编译器的职责
编译器的核心任务是将源代码转换为目标代码。在 Vue 的语境中:
| 源代码 | 目标代码 |
|---|---|
| template + script + style(SFC 单文件组件) | 浏览器可执行的 JS + CSS + HTML |
<template> 模板语法 | 渲染函数(render function) |
编译器运行在构建阶段(Node.js 侧的打包工具中),不属于运行时(runtime)。Vue 是一个兼具运行时和编译时的框架——运行时负责响应式和渲染,编译时负责将模板编译为渲染函数。
教科书式的编译器工作流
传统编译器包含以下阶段:
源代码
↓
词法分析(Lexical Analysis)→ Token 流
↓
语法分析(Syntax Analysis)→ 语法树(AST)
↓
语义分析(Semantic Analysis)→ 类型检查、作用域
↓
中间代码生成(IR Generation)
↓
优化(Optimization)
↓
目标代码生成(Code Generation)
↓
目标代码
text
词法分析
将源代码字符串拆分为一个个词法单元(Token)。类比 AI 工具(如 ChatGPT、通义千问)中的 token 概念——每个 token 就是一个最小的有意义的词或符号。
var a = 2;
→ Token 流:
[var] [a] [=] [2] [;]
text
语法分析
将 Token 流组织成语法树(AST)——一种描述代码结构的树形数据结构。
语义分析
检查程序的语义是否正确,例如:
- 类型不匹配:
int a = "hello"会报错 - 数组越界:访问超出数组长度的索引
编译前端与编译后端
| 部分 | 包含阶段 | 特点 |
|---|---|---|
| 编译前端 | 词法分析 + 语法分析 + 语义分析 | 与目标平台无关 |
| 编译后端 | 中间代码生成 + 优化 + 目标代码生成 | 依赖目标平台 |
中间代码生成和优化不一定存在于所有编译器中,属于可选阶段。
Vue3 模板编译器的工作流
Vue3 的编译器对应到上述工作流:
模板字符串(<div><p>{{ msg }}</p></div>)
↓
parse(str) → 词法分析 + 语法分析 → 模板 AST
↓
transform(ast) → 语义分析 + AST 转换 → JavaScript AST
↓
generate(jsAST) → 目标代码生成 → 渲染函数代码
text
对应三个核心方法:
| 方法 | 职责 |
|---|---|
parse | 将模板字符串解析为模板 AST |
transform | 将模板 AST 转换为 JavaScript AST |
generate | 根据 JavaScript AST 生成渲染函数代码 |
可以在 Vue SFC Playground 中直观地看到编译结果——左侧是单文件组件代码,右侧是编译后输出的渲染函数。
AST(Abstract Syntax Tree)
AST 即抽象语法树,是用树形结构描述代码的数据结构。在 Vue 编译器中涉及两种 AST:
模板 AST
描述模板的结构,是一个大 JSON 对象:
{
"type": "Root",
"children": [
{
"type": "Element",
"tag": "div",
"children": [
{
"type": "Element",
"tag": "p",
"children": [
{
"type": "Interpolation",
"content": {
"type": "Expression",
"content": "msg"
}
}
]
}
]
}
]
}
json
模板 AST 可以描述:
- 元素节点(Element):标签、属性、指令
- 文本节点(Text):静态文本
- 插值表达式(Interpolation):
{{ msg }} - 注释节点(Comment)
JavaScript AST
描述渲染函数的 JavaScript 代码结构,最终通过 generate 方法输出为可执行的 JS 代码。
本节要点
- Vue3 编译器将模板字符串转换为渲染函数,运行在构建阶段
- 编译器工作流:parse → transform → generate
- AST 是描述代码结构的树形数据结构,Vue 涉及模板 AST 和 JavaScript AST
- 编译前端(parse)与目标平台无关,编译后端(generate)与平台相关
- 可在 Vue SFC Playground 中直观体验编译过程
↑